package services;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * @author druzhencev
 * @date 19.08.2008
 */
public class MD5Hash
{
    private MD5Hash(){ /* no instance is necessary */ }

    /**
     * Calculate MD5 hash of binary array
     * @param inputDataBinary   Input byte array
     * @throws NoSuchAlgorithmException 
     * @returns                 Calculated MD5 hash
     */
    public static byte[] calculateHash(byte[] inputDataBinary) throws NoSuchAlgorithmException
    {
        return MessageDigest.getInstance("MD5").digest(inputDataBinary);
    }

    /**
     * Convert hash in byte array to string
     * @param hash Hash in byte array
     * @return Hash in string
     */
    public static String hashToHashString(byte[] hash)
    {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < hash.length; ++i)
        {
            String hex = Integer.toHexString(0xFF & hash[i]);
            if (hex.length() == 1)
                hexString.append('0');

            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * Convert hash string to hash in byte array
     * @param hashString Hash in string
     * @return Hash in byte array
     */
    public static byte[] hashStringToHash(String hashString)
    {
        byte[] bts = new byte[hashString.length() / 2];
        for (int i = 0; i < bts.length; i++)
            bts[i] = (byte) Integer.parseInt(hashString.substring(2*i, 2*i+2), 16);
        return bts;
    }

    /**
     * Calculate MD5 hash of file
     * @param fileName Name of file
     * @return Calculated MD5 hash
     * @throws IOException 
     * @throws NoSuchAlgorithmException 
     */
    public static byte[] calculateHashOfFile(String fileName) throws IOException, NoSuchAlgorithmException
    {
        // get file size
        File inputFile = new File(fileName);
        int inputFileLength = (int)inputFile.length();

        // allocate file buffer
        byte[] buffer = new byte[inputFileLength];

        // read all bytes in file to buffer
        FileInputStream fileInputStream = new FileInputStream(fileName);
        fileInputStream.read(buffer);
        fileInputStream.close();

        // return calculated hash of buffer
        return calculateHash(buffer);
    }

    /**
     * Compare to hashes
     * @param hash1 First hash in byte array
     * @param hash2 Second hash in byte array
     * @return Result of compare
     */
    public static boolean hashEquals(byte[] hash1, byte[] hash2)
    {
        return Arrays.equals(hash1,hash2);
    }
}
